package com.usermanage.util;

import com.ordercore.Util.Exception.PzException;
import com.usermanage.Service.SequenceService;
import com.usermanage.beanParam.UserBean;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.JavaType;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

import java.util.regex.Matcher;
import java.util.regex.Pattern;


import org.apache.commons.beanutils.BeanUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;


/**
 * Created by 過客 on 2018/3/26
 */
@Slf4j
@Component
public class StringUtil {

    @Resource
    private SequenceService sequenceService;

    /**
     * 每天重置订单序列号
     */
    @Scheduled(cron = "0 0 0 * * * ")
    public void clearSequenceOrder() {
        log.info("start clear seq scheduled!");
        sequenceService.clearCurrentValue("order");
        log.info("end clear seq scheduled!");
    }

    /**
     * 每天重置价目表序列号
     */
    @Scheduled(cron = "0 0 0 * * * ")
    public void clearSequenceTariff() {
        log.info("start clear seq scheduled!");
        sequenceService.clearCurrentValue("tariff");
        log.info("end clear seq scheduled!");
    }

    /**
     * 每天重置订单序列号
     */
    @Scheduled(cron = "0 0 0 * * * ")
    public void clearSequence() {
        log.info("start clear seq scheduled!");
        sequenceService.clearCurrentValue("consignee");
        log.info("end clear seq scheduled!");
    }

    /**
     * 根据类型得到流水编号
     *
     * @param num    生成的序列数字
     * @param length 生成的序列长度
     * @return
     */
    public static String getCode(String num, int length) {
        int numsum = num.length();
        StringBuffer buffer = new StringBuffer();
        if (numsum <= length) {
            int numresult = length - numsum;

            for (int i = 0; i < numresult; i++) {
                buffer.append("0");
            }
        }
        buffer.append(num);
        return buffer.toString();
    }

    /**
     * 生成消息编号
     */
    public static String getMessageCode() {
        return "MSG-" + DateUtil.getNowString() + RandomStringUtils.randomNumeric(6);
    }

    /**
     * Object转Json
     */
    public static String ObjectToJson(Object value) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            String js = mapper.writeValueAsString(value);
            return js;
        } catch (Exception ex) {
            return "Error";
        }
    }

    /**
     * Json转List<Map>
     *
     * @param json 需要转换的JSON字符串
     */
    public static List<Map> JsonToList(String json) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        List<Map> list = mapper.readValue(json, List.class);
        return list;
    }

    /**
     * 将json格式的字符串解析成Map对象
     */
    public static Map<String, String> JsonToMap(String json) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            Map<String, String> maps = mapper.readValue(json, Map.class);
            return maps;
        } catch (Exception e) {
            return null;
        }
    }

    public static Map JsonToRealMap(String json) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            Map maps = mapper.readValue(json, Map.class);
            return maps;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * Json转Object（JavaBean）
     *
     * @param json 需要转换的JSON字符串
     * @param bean JavaBean,
     * @return 拿到结果需要强转一次，因为你拿到的是Object, 例如这样调用和强转：
     * School lst =(School)StringUtil.JsonToObjectList(value, School.class);
     */
    public static <T> T JsonToBean(String json, Class<T> bean) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        JavaType javaType = mapper.getTypeFactory().uncheckedSimpleType(bean);
        return mapper.readValue(json, javaType);
    }

    /**
     * List<Map>转List<javaBean>
     *
     * @param listMap
     * @param beanClass
     * @param <T>
     * @return
     */
    public static <T> List<T> convertListMapToListBean(List<Map> listMap, Class<T> beanClass) {
        List<T> list = new ArrayList<T>();
        try {
            for (Map map : listMap) {
                // 创建一个泛型类型实例
                T t = beanClass.newInstance();
                // Map --> Bean 2: 利用org.apache.commons.beanutils 工具类实现 Map --> Bean
                BeanUtils.populate(t, map);
                list.add(t);
            }
        } catch (Exception e) {
            return null;
        }
        return list;
    }

    /**
     * 利用MD5进行加密
     *
     * @param str 待加密的字符串
     * @return 加密后的字符串
     * @throws NoSuchAlgorithmException     没有这种产生消息摘要的算法
     * @throws UnsupportedEncodingException
     */
    public static String EncoderByMd5(String str) throws NoSuchAlgorithmException, UnsupportedEncodingException {

        byte[] bs = MessageDigest.getInstance("MD5").digest(str.getBytes());
        StringBuilder sb = new StringBuilder(40);
        for (byte x : bs) {
            if ((x & 0xff) >> 4 == 0) {
                sb.append("0").append(Integer.toHexString(x & 0xff));
            } else {
                sb.append(Integer.toHexString(x & 0xff));
            }
        }
        return sb.toString();
    }

    /**
     * 得到当前时间的字符串   如：20180417153910211
     *
     * @return
     */
    public static String getTimeString() {
        Date date = new Date();
        DateFormat format = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String time = format.format(date);
        return time;
    }


    /**
     * String类型数字相加求和，并自动四舍五入保留两位小数计算
     *
     * @param str1 String类型价格
     * @param str2 String类型价格
     * @return
     */
    public static String calculate(String str1, String str2) {
        DecimalFormat df = new DecimalFormat("0.00");
        String result = df.format(new Double(str1) + new Double(str2));
        return result;
    }


    /**
     * 验证Email
     *
     * @param email
     * @return
     */
    public static boolean checkEmail(String email) {
        boolean bool = false;
        try {
            String formula = "^([a-z0-9A-Z]+[-|_|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
            Pattern pattern = Pattern.compile(formula);
            Matcher mat = pattern.matcher(email);
            bool = mat.matches();
        } catch (Exception e) {
            /**
             * 日志输出
             */
            log.error("邮箱验证异常！");
        }
        return bool;
    }


    /**
     * 计算分级
     *
     * @param parentLevel
     * @param parentId
     * @return
     */
    // 0
    // 0.1
    // 0.1.2
    // 0.1.3
    // 0.4
    public static String calculateLevel(String parentLevel, int parentId) {
        if (StringUtils.isBlank(parentLevel)) {
            return "0";
        } else {
            return StringUtils.join(parentLevel, ".", parentId);
        }
    }


    /**
     * 生成唯一标识码uuid
     *
     * @return
     */
    public static String createUuid() {
        String uuid = UUID.randomUUID().toString();//生成uuid并转换为String类型
        uuid = uuid.replace("-", ""); //因为UUID本身为32位只是生成时多了“-”，所以将它们去点就可
        return uuid;
    }

    /**
     * 判断字符串中有几个某种字符
     *
     * @param s 字符串
     * @param c 特定的字符
     * @return
     */
    public static int counter(String s, char c) {
        int count = 0;
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == c) {
                count++;
            }
        }
        return count;
    }


    /**
     * 根据类型得到流水编号
     *
     * @param num    生成的序列数字
     * @param length 生成的序列长度
     * @return
     */
    public static String getCode(String num, int length, String key) {
        int numsum = num.length();
        StringBuffer buffer = new StringBuffer(key);
        if (numsum <= length) {
            int numresult = length - numsum;

            for (int i = 0; i < numresult; i++) {
                buffer.append("0");
            }
        }
        buffer.append(num);
        return buffer.toString();
    }


    /**
     * 判断当前时间是否在有效时间内
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static boolean compare_date(String startTime, String endTime) {
        boolean bool = false;
        try {
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            Date startDate = df.parse(startTime);
            Date endDate = df.parse(endTime);
            Date now = new Date();
            if (now.getTime() > startDate.getTime() && now.getTime() < endDate.getTime()) {
                bool = true;
            }
        } catch (Exception e) {

        }
        return bool;
    }

    /**
     * 字符串转Boolean类型
     *
     * @param str
     * @return
     */
    public static boolean getBoolean(String str) {
        if (StringUtils.isNotBlank(str)) {
            return Boolean.parseBoolean(str);
        }
        return false;
    }

    /**
     * 判断开始时间是否大于结束时间
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static boolean result_date(String startTime, String endTime) {
        boolean bool = false;
        try {
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            Date startDate = df.parse(startTime);
            Date endDate = df.parse(endTime);
            if (startDate.getTime() > endDate.getTime()) {
                bool = true;
            }
        } catch (Exception e) {

        }
        return bool;
    }

    /**
     * Map复制
     */
    public static List<Map> mapCopy(List<Map> list, List<Map> list1) {
        for (Map map : list) {
            Map mapResult = new HashMap();
            Set<String> keys = map.keySet();
            for (String key : keys) {
                mapResult.put(key, map.get(key));
            }
            list1.add(mapResult);
        }
        return list1;
    }


    /**
     * 按指定舍入模式保留指定小数位数
     *
     * @param d        格式化前的小数
     * @param newScale 保留小数位数
     *                 BigDecimal 舍入模式
     * @return 格式化后的小数
     */
    public static String formatDecimal(double d, int newScale) {
//        if (newScale == 0){
//            return String.valueOf((int)d);
//        }
        BigDecimal b = new BigDecimal(d);
        double doubleValue = b.setScale(newScale, BigDecimal.ROUND_HALF_UP).doubleValue();
        return String.valueOf(doubleValue);
    }

    /**
     * 利用org.apache.commons.beanutils.BeanUtils实现
     *
     * @param userBean
     * @return
     * @throws Exception
     */
    public static Map<String, String> beanToObject(UserBean userBean) throws Exception {
        //创建Map集合对象
        Map<String, String> map = new HashMap<String, String>();
        //获取对象字节码信息,不要Object的属性
        BeanInfo beanInfo = Introspector.getBeanInfo(userBean.getClass(), Object.class);
        //获取bean对象中的所有属性
        PropertyDescriptor[] list = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor pd : list) {
            String key = pd.getName();//获取属性名
            String value = (String) pd.getReadMethod().invoke(userBean);//调用getter()方法,获取内容
            map.put(key, value);//增加到map集合当中
        }
        return map;
    }

    /**
     * 获取利用反射获取类里面的值和名称
     *
     * @param obj
     * @return
     * @throws IllegalAccessException
     */
    public static Map<?, ?> objectToMap(Object obj) {
        try {
            Map<String, Object> map = new HashMap<>();
            Class<?> clazz = obj.getClass();
            for (Field field : clazz.getDeclaredFields()) {
                field.setAccessible(true);
                String fieldName = field.getName();
                Object value = field.get(obj);
                map.put(fieldName, value);
            }
            return map;
        } catch (Exception e) {
            log.error("对象转换成Map异常！" + e);
            throw new PzException("对象转换成Map异常！");
        }
    }


    public static Map<?, ?> ConvertObjToMap(Object obj) {
        Map<String, Object> reMap = new HashMap<>();
        if (obj == null)
            return null;
        List<Field> fields = new ArrayList<>();
        List<Field> childFields;
        List<String> fieldsName = new ArrayList<>();
        Class tempClass = obj.getClass();
        while (tempClass != null) {//当父类为null的时候说明到达了最上层的父类(Object类).
            fields.addAll(Arrays.asList(tempClass.getDeclaredFields()));
            tempClass = tempClass.getSuperclass(); //得到父类,然后赋给自己
        }
        childFields = Arrays.asList(obj.getClass().getDeclaredFields());
        for (Field field : childFields) {
            fieldsName.add(field.getName());
        }
        try {
            for (Field field : fields) {
                try {
                    if (fieldsName.contains(field.getName())) {
                        Field f = obj.getClass().getDeclaredField(
                                field.getName());
                        f.setAccessible(true);
                        Object o = f.get(obj);
                        reMap.put(field.getName(), o);
                    } else {
                        Field f = obj.getClass().getSuperclass().getDeclaredField(
                                field.getName());
                        f.setAccessible(true);
                        Object o = f.get(obj);
                        reMap.put(field.getName(), o);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (SecurityException e) {
            e.printStackTrace();
        }
        return reMap;
    }


    /**
     * 此方法实现JDBCTemplate
     * 返回的Map集合对数据的自动
     * 封装功能
     * List集合存储着一系列的MAP
     * 对象，obj为一个javaBean
     *
     * @param
     * @param
     * @return
     */
    public static List parse(List list, Class obj) {
        //生成集合
        ArrayList ary = new ArrayList();
        //遍历集合中的所有数据
        for (int i = 0; i < list.size(); i++) {
            try {
                ////生成对象实历 将MAP中的所有参数封装到对象中
                Object o = addProperty((Map) list.get(i), obj.newInstance());
                //把对象加入到集合中
                ary.add(o);
            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        //返回封装好的集合
        return list;
    }

    /**
     * Map对象中的值为 name=aaa,value=bbb
     * 调用方法
     * addProperty(map,user);
     * 将自动将map中的值赋给user类
     * 此方法结合Spring框架的jdbcTemplete将非
     * 常有用
     *
     * @param
     * @param
     * @return封装好的对象
     */
    public static Object addProperty(Map map, Object obj) {
        //遍历所有名称
        Iterator it = map.keySet().iterator();
        while (it.hasNext()) {
            //取得名称
            String name = String.valueOf(it.next());
            //取得值
            String value = String.valueOf(map.get(name));

            try {
                //取得值的类形
                Class type = PropertyUtils.getPropertyType(obj, name);

                if (type != null) {
                    //设置参数
                    PropertyUtils.setProperty(obj, name, ConvertUtils.convert(value, type));

                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }

        }
        return obj;
    }
}
